package rcpexplorer.views;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.part.ViewPart;

public class ShellExplorerView extends ViewPart {
	
	private TreeViewer viewer;
	
	class ViewContentProvider implements IStructuredContentProvider, 
										   ITreeContentProvider {

		public void inputChanged(Viewer v, Object oldInput, Object newInput) {
		}
		
		public void dispose() {
		}
		
		public Object[] getElements(Object parent) {
			if (parent.equals(getViewSite())) {
				return new Object[] {new CompositeHolder(getViewSite().getShell())};
			}
			return getChildren(parent);
		}
		
		public Object getParent(Object child) {
			return null;
		}
		
		@SuppressWarnings("unchecked")
		public Object[] getChildren(Object parent) {
			if (parent instanceof CompositeHolder) {
				Composite composite = ((CompositeHolder) parent).getComposite();
				if (composite != null && (!composite.isDisposed())) {
					List children = new LinkedList();
					if (composite instanceof Shell) {
						Shell shell = (Shell) composite;
						Menu menuBar = shell.getMenuBar();
						if (menuBar != null) {
							MenuItem[] items = menuBar.getItems();
							for (MenuItem menuItem : items) {
								children.add(new WidgetHolder(menuItem));
							}
						}
					}
					Control[] controls = composite.getChildren();
					if (controls.length > 0) {
						for (Control control : controls) {
							if (control instanceof Composite) {
								children.add(new CompositeHolder((Composite) control));
							} else {
								children.add(new WidgetHolder(control));
							}
						}
					}
					return children.toArray();
				}
			} else if (parent instanceof WidgetHolder) {
				WidgetHolder widgetHolder = (WidgetHolder) parent;
				Widget widget = widgetHolder.getWidget();
				if (widget instanceof MenuItem && !widget.isDisposed()) {
					MenuItem menuItem = (MenuItem) widget;
					Menu menu = menuItem.getMenu();
					if (menu != null) {
						List children = new LinkedList();
						MenuItem[] items = menu.getItems();
						for (MenuItem item : items) {
							children.add(new WidgetHolder(item));
						}
						return children.toArray();
					}
				}
			}
			
			return new Object[0];
		}
		public boolean hasChildren(Object parent) {
			if (parent instanceof CompositeHolder) {
				Composite composite = ((CompositeHolder) parent).getComposite();
				if (composite != null && !composite.isDisposed()) {
					return composite.getChildren().length > 0;
				}
			} else if (parent instanceof WidgetHolder) {
				WidgetHolder widgetHolder = (WidgetHolder) parent;
				Widget widget = widgetHolder.getWidget();
				if (widget instanceof MenuItem && !widget.isDisposed()) {
					MenuItem menuItem = (MenuItem) widget;
					Menu menu = menuItem.getMenu();
					if (menu != null) {
						return menu.getItems().length > 0;
					}
				}
			}
			return false;
		}
	}
	
	class ViewLabelProvider extends LabelProvider {

		public String getText(Object obj) {
			if (obj instanceof WidgetHolder) {
				obj = ((WidgetHolder)obj).getWidget();
			}
			if (obj == null) {
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			Class<? extends Object> clazz = obj.getClass();
			stringBuilder.append(clazz.getSimpleName()
				+ "[" + clazz.getPackage().getName() +"]");
			return stringBuilder.toString();
		}
		
		public Image getImage(Object obj) {
			if (obj instanceof WidgetHolder) {
				obj = ((WidgetHolder)obj).getWidget();
			}
			if (obj == null) {
				return null;
			}
			if (obj instanceof Shell) {
				Shell shell = (Shell) obj;
				if (!shell.isDisposed()) {
					return shell.getImage();
				}
			} else if (obj instanceof MenuItem) {
				MenuItem menuItem = (MenuItem) obj;
				if (!menuItem.isDisposed()) {
					return menuItem.getImage();
				}
			}
			return null;
		}
		
	}

	/**
	 * The constructor.
	 */
	public ShellExplorerView() {
	}
	
	void refresh() {
		viewer.setInput(getViewSite());
		viewer.expandToLevel(2);
	}
	
	/**
	 * This is a callback that will allow us
	 * to create the viewer and initialize it.
	 */
	public void createPartControl(Composite parent) {
		viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		getSite().setSelectionProvider(viewer);
		refresh();
		
//		MenuManager menuMgr = new MenuManager("#PopupMenu");
//        menuMgr.setRemoveAllWhenShown(false);
//        menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
//        Menu menu = menuMgr.createContextMenu(viewer.getControl());
//        viewer.getControl().setMenu(menu);
//        getSite().registerContextMenu("popup", menuMgr, viewer);
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}
	
}